//package org.xukai.core.aop.springaop;
//
//import com.alibaba.fastjson.JSONObject;
//import com.raycloud.dmj.domain.Domain;
//import com.raycloud.dmj.domain.account.Company;
//import com.raycloud.dmj.domain.account.CompanyProfile;
//import com.raycloud.dmj.domain.account.Staff;
//import com.raycloud.dmj.domain.log.LogTag;
//import com.raycloud.dmj.domain.log.OpLog;
//import com.raycloud.dmj.services.log.IOpLogService;
//import com.raycloud.dmj.session.SessionException;
//import com.raycloud.dmj.web.controllers.Sessionable;
//import com.raycloud.dmj.web.utils.IpUtils;
//import org.apache.commons.lang3.StringUtils;
//import org.apache.commons.lang3.exception.ExceptionUtils;
//import org.apache.log4j.Logger;
//import org.aspectj.lang.JoinPoint;
//import org.aspectj.lang.annotation.AfterReturning;
//import org.aspectj.lang.annotation.AfterThrowing;
//import org.aspectj.lang.annotation.Aspect;
//import org.aspectj.lang.annotation.Pointcut;
//import org.aspectj.lang.reflect.MethodSignature;
//import org.springframework.aop.framework.AopProxyUtils;
//import org.springframework.expression.EvaluationContext;
//import org.xukai.common.util.HttpUtils;
//
//import javax.annotation.Resource;
//import javax.servlet.http.HttpServletRequest;
//import java.io.Serializable;
//import java.lang.reflect.Method;
//import java.util.Map;
//import java.util.concurrent.ConcurrentHashMap;
//
///**
// *
// * @author JackyLIU
// *
// */
//@Aspect
//public class OpLogAspect {
//
//	private final Logger logger = Logger.getLogger(this.getClass());
//
//	private final Map<String, LogTagOperation> operationCache = new ConcurrentHashMap<String, LogTagOperation>(64);
//
//	private final ExpressionEvaluator expressionEvaluator = new ExpressionEvaluator();
//
//	@Resource
//	private IOpLogService opLogService;
//
//	@Pointcut(value="execution(public * *(..))")
//    public void anyPublicMethod() {
//    }
//
//	@AfterReturning(value="anyPublicMethod() && @annotation(logTag)")
//	public void afterInvoke(JoinPoint joinPoint, LogTag logTag){
//		afterThrowing(joinPoint, logTag, null);
//	}
//
//	@AfterThrowing(value="anyPublicMethod() && @annotation(logTag)", throwing="ex")
//	public void afterThrowing(JoinPoint joinPoint, LogTag logTag, Exception ex){
//		try{
//			execute(joinPoint, logTag, ex);
//		}catch(Exception e){
//			logger.error(new StringBuilder("record opLog error:").append(e.getMessage()), e);
//		}
//	}
//
//	private void execute(JoinPoint joinPoint, LogTag logTag, Exception ex) throws SessionException{
//		final Object target = joinPoint.getTarget();
//		Class<?> targetClass = AopProxyUtils.ultimateTargetClass(target);
//		if (targetClass == null && target != null) {
//			targetClass = target.getClass();
//		}
//
//		final Method method = getMethod(joinPoint);
//
//		Staff staff = getStaff(joinPoint, targetClass);
//		if(null == staff){
//			staff = new Staff();
//			staff.setId(-1L);
//			staff.setCompanyId(-1L);
//			staff.setCompany(buildDefaultCompany());
//		}
//
//		// 获取request
//		HttpServletRequest request = null;
//		if(target instanceof Sessionable){
//			request = ((Sessionable)target).getRequest();
//		}
//		OpLog log = buildLog(staff, logTag, joinPoint.getArgs(), target, targetClass, method, ex, request);
//		opLogService.record(staff, log);
//	}
//
//	/**
//	 * 对于系统日志，公司使用默认的公司类型
//	 * @return
//	 */
//	private Company buildDefaultCompany(){
//		Company c = new Company();
//		c.setId(-1L);
//		CompanyProfile p = new CompanyProfile();
//		p.setCompanyId(c.getId());
//		c.setProfile(p);
//		return c;
//	}
//
//	private Method getMethod(JoinPoint joinPoint){
//		return ((MethodSignature)joinPoint.getSignature()).getMethod();
//	}
//
//	private Staff getStaff(JoinPoint joinPoint, Class<?> targetClass) throws SessionException{
//		Object[] args = joinPoint.getArgs();
//		if(joinPoint.getTarget() instanceof Sessionable){
//			Sessionable session = (Sessionable)joinPoint.getTarget();
//			Staff staff = session.getLightStaff();
//			if(null == staff.getCompany())
//				staff.setCompany(session.getCompany(staff));
//			return staff;
//		}
//		for(Object arg : args){
//			if(arg instanceof Staff)
//				return (Staff)arg;
//		}
//		return null;
//	}
//
//	private OpLog buildLog(Staff staff, LogTag tag, Object[] args, Object target, Class<?> targetClass, Method method, Exception ex, HttpServletRequest request){
//		LogTagOperation operation = getOperation(method, targetClass, tag);
//		OpLog log = new OpLog();
//		log.setCompanyId(staff.getCompanyId());
//		log.setStaffId(staff.getId());
//		log.setStaffName(staff.getName());
//		log.setAction(operation.getAction());
//		log.setDomain(operation.getDomain());
//		log.setArgs(buildArgs(method, args, operation));
//		log.setContent(buildContent(method, target, targetClass, args, operation));
//		log.setKey(buildKey(method, target, targetClass, args, operation));
//		log.setExcep(buildException(ex));
//		if(null != ex)
//			log.setIsError(1);
//
//		if(StringUtils.isEmpty(log.getDomain())){
//			// 默认设置为Domain.SYS
//			log.setDomain(Domain.SYS);
//		}
//
//		if(null != request){
//			log.setIp(HttpUtils.getRemoteAddr(request));
//		}
//		return log;
//	}
//
//	/**
//	 * args中的参数应该都需要实现 {@link Serializable}接口，如果未实现，那么序列化的内容为这个参数Class类型
//	 * @param method
//	 * @param args
//	 * @param opr
//	 * @return
//	 */
//	private String buildArgs(Method method, Object[] args, LogTagOperation opr){
//		if(!opr.isEnableArgs()){
//			return null;
//		}
//
//		// 使用JSON
//		String[] paramNames = expressionEvaluator.getParameterNames(method);
//		JSONObject json = new JSONObject();
//		for(int i = 0;(i < paramNames.length && i < args.length); i++){
//			String paramName = paramNames[i];
//			Object arg = args[i];
//			if(arg == null){
//				continue;
//			}
//
//			if(!(arg instanceof Serializable)){
//				json.put(paramName, arg.getClass());
//			}else{
//				json.put(paramName, arg);
//			}
//		}
//
//		return json.toJSONString();
//	}
//
//	private String buildContent(Method method, Object target, Class<?> targetClass, Object[] args, LogTagOperation opr){
//		if(StringUtils.isEmpty(opr.getContent()))
//			return null;
//		EvaluationContext ctx = expressionEvaluator.createEvaluationContext(method, args, target, targetClass);
//		Object content = expressionEvaluator.content(opr.getContent(), method, ctx);
//		if(null == content)
//			return null;
//		return content.toString();
//	}
//
//	private String buildKey(Method method, Object target, Class<?> targetClass, Object[] args, LogTagOperation opr){
//		if(StringUtils.isEmpty(opr.getKey()))
//			return null;
//
//		EvaluationContext ctx = expressionEvaluator.createEvaluationContext(method, args, target, targetClass);
//		Object _key = expressionEvaluator.key(opr.getKey(), method, ctx);
//		if(null == _key)
//			return null;
//		return _key.toString();
//	}
//
//	private String buildException(Exception e){
//		if(null == e)
//			return null;
//
//		return ExceptionUtils.getStackTrace(e);
//	}
//
//	private LogTagOperation getOperation(Method method, Class<?> targetClass, LogTag tag){
//		String opId = expressionEvaluator.toString(method, tag.action());
//		LogTagOperation opr = operationCache.get(opId);
//		if(null != opr)
//			return opr;
//
//		opr = new LogTagOperation();
//		opr.setId(opId);
//		// 找到Class级别的LogTag
//		LogTag ptag = targetClass.getAnnotation(LogTag.class);
//		if(null != ptag){
//			initOperation(opr, ptag);
//		}else{
//			ptag = tag;
//		}
//		initOperation(opr, tag);
//		opr.setAction(getAction(ptag, method));
//		operationCache.put(opId, opr);
//		return opr;
//	}
//
//	private String getAction(final LogTag tag, Method method){
//		if(StringUtils.isNotEmpty(tag.action()))
//			return tag.action();
//
//		return method.getName();
//	}
//
//	private LogTagOperation initOperation(final LogTagOperation opr, final LogTag ptag){
//		if(StringUtils.isNotEmpty(ptag.value())){
//			opr.setDomain(ptag.value());
//		}
//		if(StringUtils.isNotEmpty(ptag.enableArgs())){
//			opr.setEnableArgs(Boolean.valueOf(ptag.enableArgs().toLowerCase()));
//		}
//		if(StringUtils.isNotEmpty(ptag.enableResponse())){
//			opr.setEnableResponse(Boolean.valueOf(ptag.enableResponse().toLowerCase()));
//		}
//		if(StringUtils.isNotEmpty(ptag.key()))
//			opr.setKey(ptag.key());
//		if(StringUtils.isNotEmpty(ptag.content()))
//			opr.setContent(ptag.content());
//		return opr;
//	}
//}
